﻿using Elasticsearch.Net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Text.Json.Serialization;
using System.Text.Json;

namespace ReportCmp
{
    class Program
    {
        static Item curItem;
        static Dictionary<int, Item> groupItems = new Dictionary<int, Item>();
        static IList<Item> columnItems = new List<Item>();
        static IList<Item> sqlItems = new List<Item>();
        static IList<Item> functionItems = new List<Item>();
        static IList<Item> userParameterItems = new List<Item>();
        static bool isContent;
        const string patternItem = @"^ {3}(ITEMID|NAME|GROUP_ID|SOURCE|PLSLFID_ST|QUERYLFID) = ";
        const string patternTarget = @"^DEFINE  (\S+)$";
        const string tempPath = @"G:\cmpTemp\";

        static void Main(string[] args)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Console.OutputEncoding = Encoding.UTF8;

            MutBat();
            //string key = "HRCOIL_NO";
            //string formName;
            //do
            //{
            //    Console.WriteLine("請輸入rdf名稱");
            //    formName = Console.ReadLine();
            //    if (formName == "q")
            //        return;
            //    try
            //    {
            //        Run(formName, key);
            //    }
            //    catch (Exception e)
            //    {
            //        Console.WriteLine(e.Message);
            //    }
            //} while (!string.IsNullOrEmpty(formName));

            ////Run("IMRMR002", key);
            ////Console.WriteLine("DONE");
            //Console.ReadLine();
        }

        static void Run(string formName, string key)
        {
            Clear();
            CopyForm(formName);
            CmpToTxt(formName);
            TxtToJson(formName);
            //var json = TxtToJson(formName);
            PrintResult(formName,key);

            //Console.WriteLine(json);
        }

        static void Clear()
        {
            curItem = null;
            groupItems = new Dictionary<int, Item>();
            columnItems = new List<Item>();
            sqlItems = new List<Item>();
            functionItems = new List<Item>();
            userParameterItems = new List<Item>();
            isContent = false;
        }

        static void CopyForm(string formName)
        {
            File.Copy($"//192.168.0.243\\miscn\\sinodev\\{formName.Substring(0,4)}\\{formName}.rdf", $"{tempPath}{formName}.rdf", true);
        }
        static void CmpToTxt(string formName)
        {
            var process = new Process();
            process.StartInfo.FileName = @"C:\orant\bin\rwcon60.exe";
            process.StartInfo.Arguments = @$"dtype=rexfile stype=rdffile source={tempPath}{formName}.rdf dest={tempPath}{formName}.rex batch=yes OVERWRITE=yes";
            process.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
            process.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
            process.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
            process.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
            process.StartInfo.CreateNoWindow = true;          //不显示程序窗口
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            //process.StandardInput.WriteLine(cmd);
            //process.StandardInput.AutoFlush = true;
            process.Start();
            process.WaitForExit();//等待程序执行完退出进程
            process.Close();
            //File.Delete(@$"E:\work\hrcoil_no\{formName}.err");
        }


        static void MutBat()
        {
            using (var file = new StreamReader($@"{tempPath}list.txt"))
            {
                while (!file.EndOfStream)
                {
                    var line = file.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line))
                    {
                        Console.Write(line);
                        MutRun(line);
                        Console.WriteLine("--- success");
                    }
                }
            }
        }
        static void MutRun(string formName)
        {
            curItem = null;
            groupItems = new Dictionary<int, Item>();
            columnItems = new List<Item>();
            sqlItems = new List<Item>();
            functionItems = new List<Item>();
            userParameterItems = new List<Item>();
            isContent = false;
            CopyForm(formName);
            CmpToTxt(formName);
            TxtToJson(formName);
            InsertElasticsearchBulk(formName);
        }

        static void TxtToJson(string formName)
        {
            using (var file = new StreamReader(@$"{tempPath}{formName}.rex", Encoding.GetEncoding("BIG5")))
            {
                while (!file.EndOfStream)
                {
                    var line = file.ReadLine();
                    HandleLine(line);
                }
                if (curItem != null && curItem.ItemId != 0) AddItem(curItem);
            }


            //if (preLine == arrSplit)
            //{
            //    result.Add("]");
            //}
            //else if (!string.IsNullOrWhiteSpace(preMatchKey))
            //{
            //    result.Add($"\"{preMatchKey}\":{(IsArr(ToKeyName(preMatchKey)) ? "[]" : ("\"" + preVal + "\""))}");
            //}

            //var ret = string.Join("", result);
            //ret = ret.Replace("],}", "]}");
            //ret = ret.Replace("},]", "}]");

            //return ret;
        }

        static void HandleLine(string line)
        {
            if (string.IsNullOrWhiteSpace(line)) return;

            var type = IsTarget(line);
            if(type != "")
            {
                if(curItem != null)
                {
                    AddItem(curItem);
                }
                if (!IsOutTarget(type))
                    curItem = null;
                else
                    curItem = new Item { Type = type };
            }
            else
            {
                if(curItem != null)
                {
                    //curItem.Type = type;
                    AddCurItemProp(line);
                }
            }
        }

        static void AddCurItemProp(string line)
        {
            var match = Regex.Match(line, patternItem);
            string matchKey = match.Groups[1].Value.Trim();
            var hasMatchKey = !string.IsNullOrWhiteSpace(matchKey);


            if (hasMatchKey)
            {
                string val = line.Replace($"{matchKey} =", "").Replace("<<\"", "").Replace("\">>", "").Trim(); 
                switch (matchKey)
                {
                    case "NAME":
                        curItem.Name = val;
                        isContent = false;
                        break;
                    case "ITEMID":
                        curItem.ItemId = Convert.ToInt32(val);
                        isContent = false;
                        break;
                    case "GROUP_ID":
                        curItem.GroupId = Convert.ToInt32(val);
                        isContent = false;
                        break;
                    case "SOURCE":
                        curItem.Source = Convert.ToInt32(val);
                        isContent = false;
                        if (val == "2") curItem = null;
                        else if (val == "1") curItem.Type = "function";
                        else if (val == "3") curItem.Type = "userParameter";
                        break;
                    case "PLSLFID_ST":
                    case "QUERYLFID":
                        isContent = true;
                        break;
                    default:
                        isContent = false;
                        break;
                }
            }
            else if (isContent)
            {
                curItem.Content.Add(Regex.Replace(Regex.Replace(line,"^<<\"",""),"\">>$",""));
                if (Regex.IsMatch(line, "\">>$")) isContent = false;
            }

            
        }

        static void PrintResult(string formName,string key)
        {
            Console.Clear();
            Regex searchReg = new Regex(key, RegexOptions.IgnoreCase);
            IList<string> result = new List<string>();

            Console.WriteLine(formName);
            Console.WriteLine("=====================");

            foreach (var item in columnItems)
            {
                if (searchReg.IsMatch(item.Name ?? ""))
                    result.Add(item.Name);
            }
            if (result.Count > 0)
            {
                Console.WriteLine("数据库栏位");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }

            result.Clear();
            foreach (var item in functionItems)
            {
                if (searchReg.IsMatch(item.Name ?? ""))
                    result.Add(item.Name);
            }
            if (result.Count > 0)
            {
                Console.WriteLine("公式栏位");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }

            result.Clear();
            foreach (var item in sqlItems)
            {
                if (searchReg.IsMatch(string.Join("",item.Content) ?? ""))
                    result.Add(item.Name);
            }
            if (result.Count > 0)
            {
                Console.WriteLine("程式单元");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }


            result.Clear();
            foreach (var item in userParameterItems)
            {
                if (searchReg.IsMatch(item.Name ?? ""))
                    result.Add(item.Name);
            }
            if (result.Count > 0)
            {
                Console.WriteLine("使用者参数");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }
        }

        static void InsertElasticsearchBulk(string formName)
        {
            var node = new Uri("http://192.168.0.102:9200");
            var settings = new ConnectionConfiguration(node);
            var client = new ElasticLowLevelClient(settings);

            IList<ElaItem> elaColumns = new List<ElaItem>();
            IList<ElaItem> elaSqls = new List<ElaItem>();
            IList<ElaItem> elaParameters = new List<ElaItem>();
            foreach (var item in columnItems)
            {
                elaColumns.Add(new ElaItem { Name = item.Name, ReportName = formName, Type = item.Type, Content = string.Join("\r\n", item.Content) });
            }
            foreach (var item in sqlItems)
            {
                elaSqls.Add(new ElaItem { Name = item.Name, ReportName = formName, Type = item.Type, Content = string.Join("\r\n", item.Content) });
            }
            foreach (var item in userParameterItems)
            {
                elaParameters.Add(new ElaItem { Name = item.Name, ReportName = formName, Type = item.Type, Content = string.Join("\r\n", item.Content) });
            }


            IList<object> elaBulk = new List<object>();
            elaBulk.Add(new { index = new { _index = "reports", _id = formName } });
            elaBulk.Add(new
            {
                Columns = elaColumns,
                //Functions=functionItems,
                Sqls = elaSqls,
                Parameters = elaParameters,
                Name = formName
            });

            foreach(var item in elaColumns)
            {
                elaBulk.Add(new { index = new { _index = "report_items" } });
                elaBulk.Add(item);
                //if (item.Name == "vendor_plant") Console.WriteLine("vendor_plant");
            }
            foreach (var item in elaSqls)
            {
                elaBulk.Add(new { index = new { _index = "report_items" } });
                elaBulk.Add(item);
            }
            foreach (var item in elaParameters)
            {
                elaBulk.Add(new { index = new { _index = "report_items" } });
                elaBulk.Add(item);
            }

            var resp = client.Bulk<StringResponse>(PostData.MultiJson(elaBulk));
            if (!resp.Success) Console.WriteLine(resp.Body);

            //File.AppendAllText("G:\\output.txt", "\""+formName+"\":"+JsonSerializer.Serialize(elaBulk)+",");

        }

        static void AddItem(Item item)
        {
            switch (item.Type)
            {
                case "sql":sqlItems.Add(item);break;
                case "column":columnItems.Add(item);break;
                case "function":functionItems.Add(item);break;
                case "userParameter":userParameterItems.Add(item);break;
                case "group":groupItems.TryAdd(item.ItemId,item);break;
            }
        }

        static string IsTarget(string line)
        {
            var match = Regex.Match(line, patternTarget);
            string matchKey = match.Groups[1].Value.Trim();
            //if (matchKey == "SRW2_COLUMN")
            //    Console.WriteLine(matchKey);
            switch (matchKey)
            {
                case "TOOL_PLSQL": return "sql";
                case "SRW2_COLUMN": return "column";
                case "SRW2_GROUP": return "group";
                default: return matchKey;
            }
        }

        static bool IsOutTarget(string type)
        {
            switch (type)
            {
                case "sql":
                case "column":
                case "group":return true;
                default:
                    return false;
            }
        }

        class Item
        {
            public int ItemId { get; set; }
            public int GroupId { get; set; }

            /// <summary>
            /// 0 数据库栏位
            /// 1 公式栏位
            /// 2 系统参数
            /// 3 用户参数
            /// </summary>
            public int Source { get; set; }
            public string Name { get; set; }
            public string Type { get; set; }

            public IList<string> Content { get; set; }

            public Item()
            {
                this.Content = new List<string>();
            }
        }

        class ElaItem
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public string Content { get; set; }
            public string ReportName { get; set; }
        }
    }
}
